/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "面/面.h"
#include "数学/数学.h"

#include <file_文件名数据.h>


static std::unordered_map<std::u16string, S_矢量图形几何元素> g矢量图像容器;


static uint32 f_矢量图形预备数据分配(S_矢量图形构建参数& 图形参数) {
	S_PolygonDataGroup& data = 图形参数.m_路径数据;

	uint32 渐变点内存偏移 = 0;
	for (auto& e : data.渐变颜色) {
		渐变点内存偏移 += 图形参数.m_polygon_渐变颜色.size();
		图形参数.m_渐变颜色键值[e.first] = 渐变点内存偏移;

		图形参数.m_polygon_渐变颜色.insert(图形参数.m_polygon_渐变颜色.end(), e.second.begin(), e.second.end());
	}

	渐变点内存偏移 = 0;
	for (auto& e : data.效果控制) {
		uint32 key = 图形参数.m_polygon_效果控制.size();
		图形参数.m_效果控制键值[e.first] = key;

		图形参数.m_polygon_效果控制.push_back({});
	}

	uint32 元素数量 = data.graph.size();
	图形参数.m_polygon_路径顶点.resize(元素数量);
	图形参数.m_polygon_三角形.resize(元素数量);
	图形参数.m_polygon_轮廓路径.resize(元素数量);
	图形参数.m_图元属性.resize(元素数量);
	return 元素数量;
}

static S_2D图元属性 f_矢量图形效果解析(S_矢量图形构建参数& 图形参数, PolygonData& e) {
	S_PolygonDataGroup& data = 图形参数.m_路径数据;
	//e.style.线宽;
	S_2D_EffectControl 效果控制{};
	if (data.效果控制.find(e.style.效果引用) != data.效果控制.end()) {
		S_2D渐变控制& 控制 = data.效果控制[e.style.效果引用];

		auto& 渐变颜色 = data.渐变颜色[控制.colorKey];

		uint16 fillType = 控制.径向 ? DEF_2DShaderType_radialGradient : DEF_2DShaderType_linearGradient;
		效果控制.fillType_pointNum = (fillType << 16) | 渐变颜色.size();
		效果控制.Offset_Point = 图形参数.m_渐变颜色键值[控制.colorKey];

		效果控制.c1 = 控制.xy1;
		效果控制.f1 = 控制.xy2;
		效果控制.r = 控制.r;


		uint32 key_效果控制 = 图形参数.m_效果控制键值[e.style.效果引用];
		图形参数.m_polygon_效果控制[key_效果控制] = 效果控制;
	}
	else {
		e.style.填充颜色;
		效果控制.fillType_pointNum = (DEF_2DShaderType_Color << 16) | 0;
		效果控制.Offset_Point = 0;
	}
	return e.style;
}

static void f_surface_矢量图形构建(S_矢量图形构建参数& 图形参数) {
	S_PolygonDataGroup& data = 图形参数.m_路径数据;
	uint32 元素数量 = f_矢量图形预备数据分配(图形参数);

	for(int32 i=0; i<元素数量; ++i) {
		auto& e = data.graph[i];
		if(e.point.empty()) continue;

		vec2 包围大小 = data.maxBound - data.minBound;
		vec2 size = max(包围大小, data.bound);

		e.point /= max(size.x, size.y);


		auto polygon_2D路径 = f_polygon_构建2D路径(e.point, e.edges);
		if (polygon_2D路径.point.size()) {
			图形参数.m_polygon_三角形[i] = std::move(f_polygon_从链表构建三角形(polygon_2D路径));

			for (auto& e : polygon_2D路径.point) {
				图形参数.m_polygon_路径顶点[i].push_back({e, {1,1}});
			}
		}

		//轮廓索引构建
		for (auto& e : polygon_2D路径.index) {
			int32 索引数量 = max(0, int32(e.size()) - 1);

			auto it = e.begin();
			for (uint32 v = 0; v < 索引数量; ++v) {
				图形参数.m_polygon_轮廓路径[i].emplace_back(it->p);
				图形参数.m_polygon_轮廓路径[i].emplace_back(std::next(it)->p);
				++it;
			}
		}


		图形参数.m_图元属性[i] = f_矢量图形效果解析(图形参数, e);
	}
}

static void f_surface_矢量扫描图形构建(S_矢量图形构建参数& 图形参数) {
	S_PolygonDataGroup& data = 图形参数.m_路径数据;
	uint32 元素数量 = f_矢量图形预备数据分配(图形参数);

	for(int32 i=0; i<元素数量; ++i) {
		auto& e = data.graph[i];
		if(e.point.empty()) continue;

		vec2 包围大小 = data.maxBound - data.minBound;
		vec2 size = max(包围大小, data.bound);
		
		e.point -= data.minBound;
		e.point /= max(size.x, size.y);



		S_2D线段路径 polygon_2D路径线段 = f_polygon_构建2D线段路径(e.point, e.edges);

		if (polygon_2D路径线段.point.size()) {
			auto 三角形 = f_polygon_扫描构建三角形(polygon_2D路径线段);


			for (auto& e : 三角形.point) {
				图形参数.m_polygon_路径顶点[i].push_back({e, {1,1}});
			}
			图形参数.m_polygon_三角形[i] = 三角形.index;


			//轮廓索引构建
			//for (auto& e : polygon_2D路径线段.index) {
			//	auto 元素边索引 = std::vector<uint32>((uint32*)e.data(), (uint32*)e.data() + (e.size()*2));
			//	图形参数.m_polygon_轮廓路径[i] = std::move(元素边索引);
			//}
		}

		图形参数.m_图元属性[i] = f_矢量图形效果解析(图形参数, e);
	}
}


static void f_surface_矢量图形GPU数据构建(S_设备环境& ctx, S_矢量图形构建参数& 图形参数) {
	uint32 坐标起始索引 = 0;
	uint32 元素层数量 = 图形参数.m_polygon_三角形.size();
	auto key = 图形参数.name;

	auto 渐变颜色 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_渐变颜色, 0);
	f_bm_fill(渐变颜色, 图形参数.m_polygon_渐变颜色.data(), 图形参数.m_polygon_渐变颜色.size());

	auto 效果控制 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_效果控制, 0);
	f_bm_fill(效果控制, 图形参数.m_polygon_效果控制.data(), 图形参数.m_polygon_效果控制.size());

	uint32 num = 图形参数.m_polygon_效果控制.size();
	if (num) {
		auto* GPU效果控制 = f_bm_ptr<S_2D_EffectControl>(效果控制);
		for (uint32 i = 0; i < num; ++i) {
			GPU效果控制[i].Offset_Point += 渐变颜色.m_Mem.m_偏移;
		}
	}
	
	auto& 矢量元素 = g矢量图像容器[key];

	auto& 效果控制内存偏移	= 矢量元素.m_效果控制内存偏移;
	//auto& 混合模式			= 矢量元素.m_图层混合模式;
	//混合模式.resize(元素层数量);
	效果控制内存偏移.resize(元素层数量);


	for (uint32 i = 0; i < 元素层数量; ++i) {
		
		auto 顶点 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_顶点, 0);
		auto 索引 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_索引, 0);
		auto 轮廓 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_索引, 0);
		
		auto 效果控制 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_效果控制, 0);

		f_bm_fill(顶点, 图形参数.m_polygon_路径顶点[i].data(), 图形参数.m_polygon_路径顶点[i].size());

		uint32 坐标起始索引 = 顶点.m_Mem.m_偏移;

		图形参数.m_polygon_三角形[i] += 坐标起始索引;
		图形参数.m_polygon_轮廓路径[i] += 坐标起始索引;

		f_bm_fill(索引, 图形参数.m_polygon_三角形[i].data(), 图形参数.m_polygon_三角形[i].size());
		f_bm_fill(轮廓, 图形参数.m_polygon_轮廓路径[i].data(), 图形参数.m_polygon_轮廓路径[i].size());


		auto& style = 图形参数.m_路径数据.graph[i].style;
		if (style.效果引用.empty() == false) {
			uint32 控制KEY = 图形参数.m_效果控制键值[style.效果引用];
			效果控制内存偏移[i] = 控制KEY;
		}
		
		矢量元素.m_矢量图像坐标.push_back(顶点);
		矢量元素.m_矢量图像索引.push_back(索引);
		矢量元素.m_矢量图像轮廓.push_back(轮廓);
	}


	矢量元素.m_渐变颜色 = 渐变颜色;
}



void f_surface_加载矢量图像(S_设备环境& ctx, std::filesystem::path 路径, E_三角形分割方式 分割方式) {
	S_目录文件包 包;
	f_file_get目录下所有文件名(路径.string(), 包, ".svg");

	uint32 文件数量 = 包.文件.size();
	std::vector<S_矢量图形构建参数> 图形参数(文件数量);


//#pragma omp parallel for
	for (int32 i = 0; i < 文件数量; ++i) {
		std::filesystem::path path = 路径 / 包.文件[i];
		图形参数[i].m_路径数据 = f_svg_load(path.generic_string());

		if (分割方式 == E_三角形分割方式::e_分割方式_切耳) {
			f_surface_矢量图形构建(图形参数[i]);
		}
		else {
			f_surface_矢量扫描图形构建(图形参数[i]);
		}
	}

	//效果容器分配
	for (uint32 i = 0; i < 文件数量; ++i) {
		auto key = f_file_get无后缀文件名(包.文件[i]);

		图形参数[i].name = key;
		auto& e = g矢量图像容器[key];
		
		uint32 元素层数量 = 图形参数[i].m_路径数据.graph.size();
		e.m_效果控制内存偏移.resize(元素层数量);
		e.m_图元属性 = 图形参数[i].m_图元属性;
	}


	for (uint32 i = 0; i < 文件数量; ++i) {
		f_surface_矢量图形GPU数据构建(ctx, 图形参数[i]);
	}
}

void f_surface_卸载矢量图像(S_设备环境& ctx, std::u16string name) {
	if (g矢量图像容器.find(name) != g矢量图像容器.end()) {
		auto& 矢量元素 = g矢量图像容器[name];

		for (auto& e : 矢量元素.m_矢量图像坐标) {
			f_bm_erase(e);
		}
		for (auto& e : 矢量元素.m_矢量图像索引) {
			f_bm_erase(e);
		}
		for (auto& e : 矢量元素.m_矢量图像轮廓) {
			f_bm_erase(e);
		}
		for (auto& e : 矢量元素.m_效果控制) {
			f_bm_erase(e);
		}

		f_bm_erase(矢量元素.m_渐变颜色);
	}
	
}


std::vector<uvec2> f_vg_genVGraph(S_2D画布* 画布, const std::u16string& name) {
	std::vector<uvec2> 元素ID;
	return 元素ID;
	if (g矢量图像容器.find(name) != g矢量图像容器.end()) {
		auto& 矢量元素 = g矢量图像容器[name];
		uint32 num = 矢量元素.m_图元属性.size();

		元素ID.reserve(num);
		//uint32 index = 0;
		for (uint32 i = 0; i < num; ++i) {
			if (矢量元素.m_图元属性[i].填充) {
				auto 元素 = f_vg_genPolygon((*画布), *画布, 矢量元素.m_图元属性[i].混合模式, E_填充模式::e_填充面);
				元素ID.push_back({i, E_填充模式::e_填充面});
			}

			if (矢量元素.m_图元属性[i].描边) {
				auto 元素 = f_vg_genPolygon((*画布), *画布, 矢量元素.m_图元属性[i].混合模式, E_填充模式::e_填充线);
				元素ID.push_back({i, E_填充模式::e_填充线});
			}
		}
	}

	return 元素ID;
}

void f_vg_drawVGraph(S_2D画布* 画布, const std::u16string& name, std::vector<uvec2>& 元素ID) {
	if (g矢量图像容器.find(name) != g矢量图像容器.end()) {
		auto& 矢量元素 = g矢量图像容器[name];

		auto& 顶点 = 矢量元素.m_矢量图像坐标;
		auto& 索引 = 矢量元素.m_矢量图像索引;
		auto& 轮廓 = 矢量元素.m_矢量图像轮廓;


		uint32 num = 画布->m_绘制元素.size();

		for (uint32 id = 0; id < num; ++id) {
			auto& s = 画布->m_绘制元素[id];
			uvec2 index = 元素ID[id];

			std::vector<S_GPU内存块*>	形状;
			std::vector<S_RGBA8UI>		颜色;
			std::vector<vec2>			位置;
			std::vector<vec2>			大小;
			
			auto& 图元属性 = 矢量元素.m_图元属性[index.x];
			
			if (index.y == E_填充模式::e_填充面) {
				形状.emplace_back(&索引[index.x]);
				//颜色.emplace_back(图元属性.填充颜色);
				颜色.emplace_back(S_RGBA8UI{255,255,0,255});
			}
			if (图元属性.描边) {
				形状.emplace_back(&轮廓[index.x]);
				颜色.emplace_back(图元属性.描边颜色);
			}
			
			位置.emplace_back(vec2{});
			大小.emplace_back(vec2{1024,1024});
			

			f_vg_drawPolygon(*s, 1, 形状.data());
			f_vg_tranform(*s, 1, 位置.data(), 大小.data());
			f_vg_color(*s, 1, 颜色.data());
		}
	}
}

